package config

import (
	"fmt"
	"os"
	"sync"
	"time"

	"gopkg.in/yaml.v3"
)

// Config 表示应用程序的配置
type Config struct {
	Server ServerConfig `yaml:"server"`
	DNS    DNSConfig    `yaml:"dns"`
	Log    LogConfig    `yaml:"log"`
}

// ServerConfig 包含服务器相关配置
type ServerConfig struct {
	Listen    string `yaml:"listen"`
	APIListen string `yaml:"api_listen"`
}

// DNSConfig 包含 DNS 相关配置
type DNSConfig struct {
	Upstream  []UpstreamDNS `yaml:"upstream"`
	Cache     CacheConfig   `yaml:"cache"`
	QueryMode string        `yaml:"query_mode"` // 可选值: "all" 或 "random"
}

// UpstreamDNS 表示上游 DNS 服务器配置
type UpstreamDNS struct {
	Address  string        `yaml:"address"`
	Protocol string        `yaml:"protocol"`
	Timeout  time.Duration `yaml:"timeout"`
	Priority int           `yaml:"priority"`
}

// CacheConfig 包含缓存相关配置
type CacheConfig struct {
	Enabled bool          `yaml:"enabled"`
	TTL     time.Duration `yaml:"ttl"`
	MaxSize int           `yaml:"max_size"`
}

// LogConfig 包含日志相关配置
type LogConfig struct {
	Level  string `yaml:"level"`
	Format string `yaml:"format"`
	Output string `yaml:"output"`
	File   string `yaml:"file"`
}

var (
	instance *Config
	once     sync.Once
	mu       sync.RWMutex
)

// LoadConfig 从指定路径加载配置文件
func LoadConfig(path string) (*Config, error) {
	once.Do(func() {
		instance = &Config{}
	})

	mu.Lock()
	defer mu.Unlock()

	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("failed to read config file: %w", err)
	}

	if err := yaml.Unmarshal(data, instance); err != nil {
		return nil, fmt.Errorf("failed to parse config file: %w", err)
	}

	// 验证配置
	if err := validateConfig(instance); err != nil {
		return nil, err
	}

	return instance, nil
}

// GetConfig 返回当前配置实例
func GetConfig() *Config {
	mu.RLock()
	defer mu.RUnlock()
	return instance
}

// ReloadConfig 重新加载配置文件
func ReloadConfig(path string) error {
	_, err := LoadConfig(path)
	return err
}

// validateConfig 验证配置是否有效
func validateConfig(cfg *Config) error {
	// 验证服务器配置
	if cfg.Server.Listen == "" {
		return fmt.Errorf("server.listen is required")
	}
	if cfg.Server.APIListen == "" {
		return fmt.Errorf("server.api_listen is required")
	}

	// 验证 DNS 配置
	if len(cfg.DNS.Upstream) == 0 {
		return fmt.Errorf("at least one upstream DNS server is required")
	}

	for i, upstream := range cfg.DNS.Upstream {
		if upstream.Address == "" {
			return fmt.Errorf("dns.upstream[%d].address is required", i)
		}
		if upstream.Protocol == "" {
			return fmt.Errorf("dns.upstream[%d].protocol is required", i)
		}
		if upstream.Protocol != "udp" && upstream.Protocol != "tcp" {
			return fmt.Errorf("dns.upstream[%d].protocol must be 'udp' or 'tcp'", i)
		}
	}

	// 验证查询模式
	if cfg.DNS.QueryMode == "" {
		// 设置默认值为 random
		cfg.DNS.QueryMode = "random"
	} else if cfg.DNS.QueryMode != "all" && cfg.DNS.QueryMode != "random" {
		return fmt.Errorf("dns.query_mode must be 'all' or 'random'")
	}

	// 验证日志配置
	validLevels := map[string]bool{"debug": true, "info": true, "warn": true, "error": true}
	if !validLevels[cfg.Log.Level] {
		return fmt.Errorf("log.level must be one of 'debug', 'info', 'warn', 'error'")
	}

	validFormats := map[string]bool{"json": true, "text": true}
	if !validFormats[cfg.Log.Format] {
		return fmt.Errorf("log.format must be one of 'json', 'text'")
	}

	validOutputs := map[string]bool{"stdout": true, "file": true}
	if !validOutputs[cfg.Log.Output] {
		return fmt.Errorf("log.output must be one of 'stdout', 'file'")
	}

	if cfg.Log.Output == "file" && cfg.Log.File == "" {
		return fmt.Errorf("log.file is required when log.output is 'file'")
	}

	return nil
}

// SaveConfig 将当前配置保存到文件
func SaveConfig(path string) error {
	mu.RLock()
	defer mu.RUnlock()

	data, err := yaml.Marshal(instance)
	if err != nil {
		return fmt.Errorf("failed to marshal config: %w", err)
	}

	if err := os.WriteFile(path, data, 0644); err != nil {
		return fmt.Errorf("failed to write config file: %w", err)
	}

	return nil
}
